<?php
/*
  常用工具类
 */

use speed\Config;

/**
 * Notes:传入类型 获取 某时间段的时间戳
 * User: 戴杰
 * Date: 2019/4/9 0009
 * @param int $type 1 今天  2昨天  3本周 4本月  5上周  默认 1本天
 * @return array  返回数组 start 开始时间  end 结束时间
 */
//

//写日志记录
function debug_log($title, $data)
{
    $path = "./data/log/";
    mkdirs($path);
    $file = date('Ymd') . '.txt';
    @$content = file_get_contents($path . $file);
    file_put_contents($path . $file, $content . "\r\n\r\n" . $title . "  " . date('Y-m-d H:i:s') . "\r\n" . json_encode($data, JSON_UNESCAPED_UNICODE));
}

//修改图片尺寸
function resize_image($filename, $tmpname, $xmax, $ymax)
{
    $ext = explode(".", $filename);
    $ext = $ext[count($ext) - 1];

    if ($ext == "jpg" || $ext == "jpeg")
        $im = imagecreatefromjpeg($tmpname);
    elseif ($ext == "png")
        $im = imagecreatefrompng($tmpname);
    elseif ($ext == "gif")
        $im = imagecreatefromgif($tmpname);

    $x = imagesx($im);
    $y = imagesy($im);

    if ($x <= $xmax && $y <= $ymax)
        return $im;

    if ($x >= $y) {
        $newx = $xmax;
        $newy = $newx * $y / $x;
    } else {
        $newy = $ymax;
        $newx = $x / $y * $newy;
    }

    $im2 = imagecreatetruecolor($newx, $newy);
    imagecopyresized($im2, $im, 0, 0, 0, 0, floor($newx), floor($newy), $x, $y);
    return $im2;
}


//将字符串变成数组
function convertUrlQuery($query)
{
    $queryParts = explode('&', $query);
    $params = array();
    foreach ($queryParts as $param) {
        $item = explode('=', $param);
        $params[$item[0]] = $item[1];
    }
    return $params;
}

/**
 * 将参数变为字符串
 * @param $array_query
 * @return string string 'm=content&c=index&a=lists&catid=6&area=0&author=0&h=0&region=0&s=1&page=1' (length=73)
 */
function getUrlQuery($array_query)
{
    $tmp = array();
    foreach ($array_query as $k => $param) {
        $tmp[] = $k . '=' . $param;
    }
    $params = implode('&', $tmp);
    return $params;
}


// 1 今天 2 昨天 5本月 6 上月
function getTime($type = 1)
{
    $timestamp = time();
    switch ($type) {
        case 2://昨天
            $start_time = mktime(0, 0, 0, date('m'), date('d') - 1, date('Y'));
            $end_time = mktime(0, 0, 0, date('m'), date('d'), date('Y')) - 1;
            break;
        case 3://本周
            $start_time = strtotime(date('Y-m-d', strtotime("this week Monday", $timestamp)));
            $end_time = strtotime(date('Y-m-d', strtotime("this week Sunday", $timestamp))) + 24 * 3600 - 1;
            break;
        case 4://上周
            $start_time = mktime(0, 0, 0, date('m'), date('d') - date('w') + 1 - 7, date('Y'));
            $end_time = mktime(23, 59, 59, date('m'), date('d') - date('w') + 7 - 7, date('Y'));
            break;
        case 5://本月
            $start_time = mktime(0, 0, 0, date('m'), 1, date('Y'));
            $end_time = mktime(23, 59, 59, date('m'), date('t'), date('Y'));
            break;
        case 6://上月
            $start_time = strtotime(date('Y-m-01 00:00:00', strtotime('-1 month')));
            $end_time = strtotime(date("Y-m-d 23:59:59", strtotime(-date('d') . 'day')));
            break;
        case 7://近三月
            $start_time = strtotime("-0 year -3 month -0 day");
            $end_time = $timestamp;
            break;
        default://今天
            $start_time = strtotime(date("Y-m-d"), $timestamp);
            $end_time = $timestamp;
            break;
    }
    return ['start' => $start_time, 'end' => $end_time];
}


/**
 * 根据现有的参数和密钥计算出sign值
 * @param Array $params 参数集合
 * @return String
 */
function create_sign($params = null)
{
    if ($params && is_array($params)) {
        ksort($params);
        $str = '2017_miaosha';
        foreach ($params as $key => $value) {
            if ($key != 'sign') {
                $str .= $key . $value;
            }
        }
        return strtoupper(md5($str));
    }
    return '';
}


// 保存登录的cookie信息
function save_auth_cookie($auth_cookie)
{
    $now = time();
    header('P3P: CP="ALL ADM DEV PSAi COM OUR OTRo STP IND ONL"');
    $datalist = array();

    foreach ($auth_cookie as $key => $value) {
        $datalist[] = $key . '=' . urlencode($value);
    }
    $sign = create_sign($auth_cookie);
    $datalist[] = 'sign=' . $sign;
    $cookie = implode('&', $datalist);
    $expire = $auth_cookie['third_expires'];
    if ($expire <= $now) { // 默认保持一个月的时间
        $expire = $now + 86400;
    }
    setcookie(AUTH_COOKIE_NAME, $cookie, $expire, '/', '');
}

// 退出登录，清空cookie信息
function clear_auth_cookie()
{
    setcookie(AUTH_COOKIE_NAME, '', 1, '/', '');
}

// 获取登录信息
function get_login_userinfo()
{
    $datalist = array();
    $cookie = null;
    if (isset($_COOKIE[AUTH_COOKIE_NAME])) {
        $cookie = $_COOKIE[AUTH_COOKIE_NAME];
    }
    if ($cookie) {
        $arr_cookie = explode('&', $cookie);
        foreach ($arr_cookie as $str_cookie) {
            $index = strpos($str_cookie, '=');
            if ($index !== false) {
                $datalist[substr($str_cookie, 0, $index)] = urldecode(substr($str_cookie, $index + 1));
            } else {
                $datalist[$str_cookie] = '';
            }
        }
        // 验证码是否被篡改
        $sign = $datalist['sign'];
        $new_sign = create_sign($datalist);
        if ($sign != $new_sign) { // cookie校验失败
            return null;
        } else {
            return $datalist;
        }
    }
}

// 根据明文生成密文   密码加密
function password_md5($pwd, $salt = '大兔白白')
{
    return md5($pwd . substr(md5($salt), 0, 15));
}


//多维数组排序
function arraySort($arr, $keys, $type = 'asc')
{
    $keysvalue = $new_array = array();
    foreach ($arr as $k => $v) {
        $keysvalue[$k] = $v[$keys];
    }
    $type == 'asc' ? asort($keysvalue) : arsort($keysvalue);
    reset($keysvalue);
    foreach ($keysvalue as $k => $v) {
        $new_array[$k] = $arr[$k];
    }
    return $new_array;
}

//给文字追加html标签样式
function tpl_add_status($str, array $statusArr)
{
    if ($statusArr[$str]) {
        return "<span class='label label-" . $statusArr[$str] . "'>{$str}</span>";
    } else {
        return $str;
    }
}

//文本取中间
function getSubstr($str, $leftStr, $rightStr)
{
    $left = strpos($str, $leftStr);
    if ($left === false) return '';
    $right = strpos($str, $rightStr, $left + strlen($leftStr));
    if ($right === false) return '';
    if ($left < 0 or $right < $left) return '';
    return substr($str, $left + strlen($leftStr), $right - $left - strlen($leftStr));
}


/*
	自定义封装函数存放位置
 */
//判断是否是ajax请求
function isAjax()
{
    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
        return true;
    } else {
        return arg('var_ajax') ? true : false;
    }
}

//获取ip
function getIp()
{
    if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
        $ip = getenv("HTTP_CLIENT_IP");
    else
        if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        else
            if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
                $ip = getenv("REMOTE_ADDR");
            else
                if (isset ($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
                    $ip = $_SERVER['REMOTE_ADDR'];
                else
                    $ip = "unknown";
    return ($ip);
}

/**
 * @param $maxpage  总页数
 * @param $page    当前页
 * @param string $para 翻页参数(不需要写$page),如http://www.example.com/article.php?p=3&id=1，$para参数就应该设为'&id=1'
 * @param string $ajax 是否要转换成ajax模式 默认不转换
 * @return string  返回的输出分页html内容
 */
function multipage($maxpage, $page, $para = '', $ajax = true)
{
    $multipage = '';  //输出的分页内容
    $listnum = 5;     //同时显示的最多可点击页面
    if ($maxpage < 2) {
        return '';
    } else {
        $offset = 2;
        if ($maxpage <= $listnum) {
            $from = 1;
            $to = $maxpage;
        } else {
            $from = $page - $offset; //起始页
            $to = $from + $listnum - 1;  //终止页
            if ($from < 1) {
                $to = $page + 1 - $from;
                $from = 1;
                if ($to - $from < $listnum) {
                    $to = $listnum;
                }
            } elseif ($to > $maxpage) {
                $from = $maxpage - $listnum + 1;
                $to = $maxpage;
            }
        }
        $multipage .= ($page - $offset > 1 && $maxpage >= $page ? '<li><a href="?p=1' . $para . '" >1...</a></li>' : '') .
            ($page > 1 ? '<li><a href="?p=' . ($page - 1) . $para . '" >&laquo;</a></li>' : '');

        for ($i = $from; $i <= $to; $i++) {
            $multipage .= $i == $page ? '<li class="active"><a href="?p=' . $i . $para . '" >' . $i . '</a></li>' : '<li><a href="?p=' . $i . $para . '" >' . $i . '</a></li>';
        }

        $multipage .= ($page < $maxpage ? '<li><a href="?p=' . ($page + 1) . $para . '" >&raquo;</a></li>' : '') .
            ($to < $maxpage ? '<li><a href="?p=' . $maxpage . $para . '" class="last" >...' . $maxpage . '</a></li>' : '');
        // $multipage .=  ' <li><a href="#" ><input type="text" size="3"  onkeydown="if(event.keyCode==13) {self.window.location=\'?p=\'+this.value+\''.$para.'\'; return false;}" ></a></li>';
        $multipage = $multipage ? '<ul class="pagination">' . $multipage . '</ul>' : '';
    }

    return $ajax ? preg_replace("(<a[^>]*p[=|/](\d+).+?>(.+?)<\/a>)", "<a href='javascript:ajax_page($1);'>$2</a>", $multipage) : $multipage;
}


function ob_gzip($content) // $content 就是要压缩的页面内容，或者说饼干原料 
{
    if (!headers_sent() && // 如果页面头部信息还没有输出
        extension_loaded("zlib") && // 而且zlib扩展已经加载到PHP中
        strstr($_SERVER["HTTP_ACCEPT_ENCODING"], "gzip")) //而且浏览器说它可以接受GZIP的页面
    {
        $content = gzencode($content . " \n//此页已压缩", 9); //为准备压缩的内容贴上“//此页已压缩”的注释标签，然后用zlib提供的gzencode()函数执行级别为9的压缩，这个参数值范围是0-9，0表示无压缩，9表示最大压缩，当然压缩程度越高越费CPU。
        //然后用header()函数给浏览器发送一些头部信息，告诉浏览器这个页面已经用GZIP压缩过了！
        header("Content-Encoding: gzip");
        header("Vary: Accept-Encoding");
        header("Content-Length: " . strlen($content));
    }
    return $content; //返回压缩的内容，或者说把压缩好的饼干送回工作台。 
}


/**
 * spAccess 数据缓存及存取程序
 *
 * @param method    数据存取模式，取值"w"为存入数据，取值"r"读取数据，取值"c"为删除数据
 * @param name    标识数据的名称
 * @param value    存入的值，在读取数据和删除数据的模式下均为NULL
 * @param life_time    变量的生存时间，默认为永久保存
 */
function spAccess($method, $name, $value = NULL, $life_time = -1)
{
    // 准备缓存目录和缓存文件名称，缓存文件名称为$name的MD5值，文件后缀为php
    if (!is_dir($GLOBALS['sp_cache'])) mkdirs($GLOBALS['sp_cache']);
    $sfile = $GLOBALS['sp_cache'] . '/' . md5($name) . ".php";
    // 对$method进行判断，分别进行读写删的操作
    if ('w' == $method) {
        // 写数据，在$life_time为-1的时候，将增大$life_time值以令$life_time不过期
        $life_time = (-1 == $life_time) ? '300000000' : $life_time;
        // 准备存入缓存文件的数据，缓存文件使用PHP的die();函数以便保证内容安全，
        $value = '<?php die();?>' . (time() + $life_time) . serialize($value); // 数据被序列化后保存
        return file_put_contents($sfile, $value);
    } elseif ('c' == $method) {
        // 清除数据，直接移除改缓存文件
        return @unlink($sfile);
    } else {
        // 读数据，检查文件是否可读，同时将去除缓存数据前部的内容以返回
        if (!is_readable($sfile)) return FALSE;
        $arg_data = file_get_contents($sfile);
        // 获取文件保存的$life_time，检查缓存是否过期
        if (substr($arg_data, 14, 10) < time()) {
            @unlink($sfile); // 过期则移除缓存文件，返回FALSE
            return FALSE;
        }
        return unserialize(substr($arg_data, 24)); // 数据反序列化后返回
    }

}

//递归循环创建目录
function mkdirs($dir, $mode = 0777)
{
    if (!is_dir($dir)) {
        mkdirs(dirname($dir), $mode);
        return mkdir($dir, $mode);
    }
    return true;
}

/**
 * curl HTTP请求
 * @param  [type]  $url      网址
 * @param  string $opt 提交参数
 * @param  [type]  &$header  取回的头信息
 * @param  boolean $redirect 是否重定向
 * @param  boolean $ssl 验证https证书
 * @return [type]            返回信息
 */
function httpRequest($url, $opt = 'GET', &$code = null, &$header = null, $redirect = true, $ssl = false)
{
    //初始化
    $ch = curl_init($url);
    //配置设置
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $ssl);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $ssl);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $redirect);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);                 #返回结果
    curl_setopt($ch, CURLOPT_HEADER, true);                         #显示头信息
    // curl_setopt($ch, CURLOPT_ENCODING ,'gzip');
    if (is_array($opt)) {
        //转小写
        $opt = array_change_key_case($opt, CASE_LOWER);
        if (isset($opt['type']) && strtoupper($opt['type']) == 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, (isset($opt['data']) ? $opt['data'] : ''));
        }
        if (array_key_exists('ua', $opt))
            curl_setopt($ch, CURLOPT_USERAGENT, $opt['ua']);
        if (array_key_exists('header', $opt)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, (array)$opt['header']);
        }
        if (array_key_exists('cookie', $opt))
            curl_setopt($ch, CURLOPT_COOKIE, $opt['cookie']);
        if (array_key_exists('referer', $opt))
            curl_setopt($ch, CURLOPT_REFERER, $opt['referer']);
    } else {
        if (strtoupper((string)$opt) == 'POST')
            curl_setopt($ch, CURLOPT_POST, true);
    }
    $result = curl_exec($ch);
    if (curl_errno($ch)) {
        $result = curl_error($ch);
    } else {
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $length = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $header = substr($result, 0, $length);

        $result = substr($result, $length);
    }
    //释放
    curl_close($ch);
    return $result;
}

//取回cookie
function getCookie($header)
{
    preg_match_all('/Set-Cookie: (.*)/i', $header, $str); //正则匹配
    $str_new = [];
    foreach ($str[1] as $k => $v) {
        if ($v)
            $str_new[$k] = str_replace(substr($v, -1), '', $v);
    }
    if ($str_new)
        return join(';', $str_new) . ";";
    return '';
}


/**
 * 加密函数
 * @param string $txt 需加密的字符串
 * @param string $key 加密密钥，默认读取data_auth_key配置
 * @return string 加密后的字符串
 */
function encrypt($txt, $key = '兔白白')
{


    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=_";
    $nh = rand(0, 64);
    $ch = $chars[$nh];
    $mdKey = md5($key . $ch);
    $mdKey = substr($mdKey, $nh % 8, $nh % 8 + 7);
    $txt = base64_encode($txt);
    $tmp = '';
    $k = 0;
    for ($i = 0; $i < strlen($txt); $i++) {
        $k = $k == strlen($mdKey) ? 0 : $k;
        $j = ($nh + strpos($chars, $txt [$i]) + ord($mdKey[$k++])) % 64;
        $tmp .= $chars[$j];
    }
    return $ch . $tmp;
}

/**
 * 解密函数
 * @param string $txt 待解密的字符串
 * @param string $key 解密密钥，默认读取data_auth_key配置
 * @return string 解密后的字符串
 */
function decrypt($txt, $key = '兔白白')
{
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=_";
    $ch = $txt[0];
    $nh = strpos($chars, $ch);
    $mdKey = md5($key . $ch);
    $mdKey = substr($mdKey, $nh % 8, $nh % 8 + 7);
    $txt = substr($txt, 1);
    $tmp = '';
    $k = 0;
    for ($i = 0; $i < strlen($txt); $i++) {
        $k = $k == strlen($mdKey) ? 0 : $k;
        $j = strpos($chars, $txt[$i]) - $nh - ord($mdKey[$k++]);
        while ($j < 0) {
            $j += 64;
        }
        $tmp .= $chars[$j];
    }
    return base64_decode($tmp);
}

function get_host()
{
    $http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';
    return $http_type . $_SERVER['HTTP_HOST']; //. $_SERVER['REQUEST_URI']
}


/**
 * Notes:异步curl 请求
 * User: 戴杰
 * Date: 2020/9/28 0028
 * @param array $data 批量请求的网站列表 二维 数组 ['url'=>'http://www.baidu.com','data'=>[]]
 * @param int $timeout 超时时间
 * @param bool $isGetcontent 是否获取请求返回值
 * @return array|null
 */
function getMultiCurlResult($data = [], $timeout = 120, $isGetcontent = false)
{
    $request = [];//请求资源组
    $result = [];//返回信息
    $requestResource = curl_multi_init();
    foreach ($data as $k => $v) {
        $option = [
            CURLOPT_TIMEOUT => $timeout,//请求超时时间,防止死循环
            CURLOPT_RETURNTRANSFER => true,//获取的信息以文件流的形式返回，而不是直接输出。
        ];
        //如果不存在url 则直接返回null
        if (!isset($v['url']) || !$v['url']) return null;
        $option[CURLOPT_URL] = trim($v['url']);

        //如果不是https  则ssl false
        if (stripos($v['url'], 'https') === 0) $option[CURLOPT_SSL_VERIFYPEER] = false;

        if (isset($v['data'])) {//如果设置了请求参数,则是POST请求
            $option[CURLOPT_POST] = true;
            $option[CURLOPT_POSTFIELDS] = http_build_query($v['data']);
        }

        //启动一个curl会话
        $request[$k] = curl_init();
        //设置请求选项
        curl_setopt_array($request[$k], $option);
        //添加请求句柄
        curl_multi_add_handle($requestResource, $request[$k]);
        $result[$request[$k]] = [
            'handle' => $request[$k],
            'url' => $v['url'],
        ];
    }

    $running = null;
    do {//执行批处理句柄
        // CURLOPT_RETURNTRANSFER 如果为0,这里会直接输出获取到的内容.如果为1,后面可以用 curl_multi_getcontent 获取内容.
        curl_multi_exec($requestResource, $running);
        $info = curl_multi_info_read($requestResource);
        if ($info !== false) {
            // 0 正常 7 请求响应失败  28 请求超过设置时间(可以增加$timeout试试)
            $result[$info['handle']]['result'] = $info['result'];
            $result[$info['handle']]['msg'] = $info['msg'];
        }
        //阻塞直到cURL批处理连接中有活动连接,不加这个会导致CPU负载超过90%.
        curl_multi_select($requestResource);
    } while ($running > 0);

    //获取 请求返回值
    if ($isGetcontent) {
        foreach ($request as $k => $v) {
            //如果设置了CURLOPT_RETURNTRANSFER，则返回获取的输出的文本流
            $result[$v]['content'] = curl_multi_getcontent($v);
            //移除curl批处理句柄资源中的某个句柄资源
            curl_multi_remove_handle($requestResource, $v);
        }
    }
    //关闭批处理句柄
    curl_multi_close($requestResource);
    return $result;
}


//取时间间隔
function timediff($begin_time, $end_time)
{
    $mode = 0;
    if ($begin_time < $end_time) {
        $starttime = $begin_time;
        $endtime = $end_time;
        $mode = 1;
    } else {
        $starttime = $end_time;
        $endtime = $begin_time;
    }
    $timediff = $endtime - $starttime;
//    dump($timediff / 86400);
    $days = intval($timediff / 86400) * ($mode ?: -1);
    $remain = $timediff % 86400;
    $hours = intval($remain / 3600);
    $remain = $remain % 3600;
    $mins = intval($remain / 60);
    $secs = $remain % 60;
    $res = array("day" => $days, "hour" => $hours, "min" => $mins, "sec" => $secs);
    return $res;
}


function success($msg = 'success', $data = array())
{
    error($msg, 200, $data);
}

/**
 * Notes:接口数据返回格式
 * User: 戴杰
 * Date: 2019/4/9 0009
 * @param $code
 * @param $msg
 * @param $data
 */
function error($msg, $code = -1, $data = array())
{
    @header('Content-Type: application/json');
    echo json_encode(['code' => $code, 'msg' => $msg, 'data' => $data,'message'=>$msg], JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * 随机字符
 * @param int $length 长度
 * @param string $type 类型
 * @param int $convert 转换大小写 1大写 0小写
 * @return string
 */
function random($length = 10, $type = 'letter', $convert = 0)
{
    $config = array(
        'number' => '1234567890',
        'letter' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
        'string' => 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789',
        'all' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
    );

    if (!isset($config[$type])) $type = 'letter';
    $string = $config[$type];

    $code = '';
    $strlen = strlen($string) - 1;
    for ($i = 0; $i < $length; $i++) {
        $code .= $string[mt_rand(0, $strlen)];
    }
    if (!empty($convert)) {
        $code = ($convert > 0) ? strtoupper($code) : strtolower($code);
    }
    return $code;
}
